package models

import (
	"encoding/json"
	"fmt"
	//"github.com/openkruise/rollouts/api/v1alpha1"
	"github.com/openkruise/rollouts/api/v1alpha1"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"sigs.k8s.io/yaml"
	"strings"
)

// 采集任务 和机器的关系
// 1对多 机器只能属于1个采集任务
// 新建采集任务 就需要填入ip
// 主配置文件池
// job 对象 机器：ip+port
//
//	2 k8s 的服务发现：集群外部采集
//
// D:\nyy_work\go_path\src\github.com\prometheus\prometheus\model\rulefmt\rulefmt.go
type CicdDeployItem struct {
	Model          // 不用每次写ID 和 createAt了
	RunType string `json:"runType"  gorm:"comment:服务发布项类型k8s和虚拟机" `

	// 下面是global段  gorm:"uniqueIndex:jid_hostip;"`
	UserID          uint
	TreeNodeId      uint `json:"treeNodeId" gorm:"uniqueIndex;comment:绑定到哪个节点的 绑定第4层级 app维度"`
	GitlabProjectId int  `json:"gitlabProjectId" gorm:"comment:项目的projectid" `

	GitlabRepository string `json:"gitlabRepository" gorm:"comment: gitlab仓库名称"`
	ImagePrefix      string `json:"imagePrefix" gorm:"comment: harbor镜像名称前缀"`

	//Replicas    int `json:"replicas" gorm:"comment: 副本数"`
	// 服务发布项的顺序
	Stages string `json:"stages" gorm:"type:text;comment:服务发布项的顺序 json 字符串 结构 {name :预发布环境,cluster:bigdevops}"`

	// 灰度发布支持

	CanaryStrategyYamlString string `json:"canaryStrategyYamlString" gorm:"type:text;comment: 是yaml的字符串，unmarshal塞入"`
	IsCanary                 bool   `json:"isCanary" gorm:"comment:是否灰度 false"`

	StagesFront    []DeployStage `json:"stagesFront" gorm:"-"`
	CreateUserName string        `json:"createUserName" gorm:"-"`
	NodePath       string        `json:"nodePath" gorm:"-"` // a.b.c.d
	Key            string        `json:"key" gorm:"-"`      //给前端表格
	StreeNodeObj   *StreeNode    `json:"streeNodeObj" gorm:"-"`
}

type DeployStage struct {
	Name     string `json:"name"`
	Cluster  string `json:"cluster"`
	K8sAppId uint   `json:"k8sAppId"`
	Replicas int    `json:"replicas" `
}

func (obj *CicdDeployItem) ValidateCanaryStrategyYamlString() error {
	var canaryStrategyObj *v1alpha1.CanaryStrategy
	return yaml.Unmarshal([]byte(obj.CanaryStrategyYamlString), &canaryStrategyObj)

}
func (obj *CicdDeployItem) Create() error {
	return Db.Create(obj).Error

}
func (obj *CicdDeployItem) DeleteOne() error {

	return Db.Select(clause.Associations).Unscoped().Delete(obj).Error

}

func (obj *CicdDeployItem) CreateOne() error {
	return Db.Create(obj).Error

}

func (obj *CicdDeployItem) UpdateOne() error {
	return Db.Debug().Where("id = ?", obj.ID).Updates(obj).Error

}

func (obj *CicdDeployItem) GenMapFromKvs(kvs []string) map[string]string {

	labelsM := map[string]string{}
	for _, i := range kvs {
		kvs := strings.Split(i, "=")
		if len(kvs) != 2 {
			continue
		}
		k := kvs[0]
		v := kvs[1]
		labelsM[k] = v
	}
	return labelsM

}

// 0值替换 前转后
// 1. gitlab projectid去查询一下name 塞入数据库
// 2. k8sappid也要查一下cluster

func (obj *CicdDeployItem) FillDefaultData() (err error) {
	fStage := []DeployStage{}
	for _, stage := range obj.StagesFront {

		dbK8sApp, err := GetK8sAppById(int(stage.K8sAppId))
		if err != nil {
			continue
		}
		fStage = append(fStage, DeployStage{
			Name:     stage.Name,
			Cluster:  dbK8sApp.Cluster,
			K8sAppId: stage.K8sAppId,
			Replicas: stage.Replicas,
		})

	}

	stagebytes, err := json.Marshal(fStage)
	if err != nil {
		return err
	}
	obj.Stages = string(stagebytes)

	//  gitlab projectid去查询一下name 塞入数据库

	return nil

}

func (obj *CicdDeployItem) FillStreeNodeObj() error {
	dbNode, err := GetStreeNodeById(int(obj.TreeNodeId))
	if err != nil {
		return err
	}
	obj.StreeNodeObj = dbNode
	//obj.StreeNodeObj.FillFrontAllDataSimple()
	obj.StreeNodeObj.FillFrontAllData()
	obj.NodePath = obj.StreeNodeObj.NodePath
	return nil
}

func (obj *CicdDeployItem) FillFrontAllData() (err error) {
	dbUser, _ := GetUserById(int(obj.UserID))
	if dbUser != nil {
		obj.CreateUserName = dbUser.Username
	}
	err = obj.FillStreeNodeObj()
	if err != nil {
		return err
	}
	// 添加stage
	var stages []DeployStage
	err = json.Unmarshal([]byte(obj.Stages), &stages)
	if err != nil {
		return err
	}

	obj.StagesFront = stages
	return

}
func GetCicdDeployItemAll() (objs []*CicdDeployItem, err error) {
	err = Db.Find(&objs).Error
	return
}

func GetCicdDeployItemCount() int {
	var count int64
	Db.Table("form_designs").Count(&count)
	return int(count)
}

func GetCicdDeployItemByLevel(level int) (objs []*CicdDeployItem, err error) {
	err = Db.Where("level = ?", level).Preload("OpsAdmins").Find(&objs).Error
	return
}

// select * from ecs where
func GetCicdDeployItemByIdsWithLimitOffset(ids []int, limit, offset int) (objs []*CicdDeployItem, err error) {
	err = Db.Limit(limit).Offset(offset).Find(&objs, ids).Error
	return
}

// 查询这个节点池管理的采集Job
func GetCicdDeployItemByPoolId(poolId uint) (objs []*CicdDeployItem, err error) {

	err = Db.Where("enable=1 and pool_id = ?", poolId).Find(&objs).Error
	return
}

func GetCicdDeployItemWith(sendGroupId uint) (objs []*CicdDeployItem, err error) {

	err = Db.Where("send_group_id = ?", sendGroupId).Find(&objs).Error
	return
}

func GetCicdDeployItemById(id int) (*CicdDeployItem, error) {

	var dbObj CicdDeployItem
	err := Db.Where("id = ?", id).First(&dbObj).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("CicdDeployItem不存在")
		}
		return nil, fmt.Errorf("数据库错误:%w", err)
	}
	return &dbObj, nil

}
func GetCicdDeployItemByStreeNodeId(treeNodeId int) (*CicdDeployItem, error) {

	var dbObj CicdDeployItem
	err := Db.Where("tree_node_id = ?", treeNodeId).First(&dbObj).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("CicdDeployItem不存在")
		}
		return nil, fmt.Errorf("数据库错误:%w", err)
	}
	return &dbObj, nil

}

func GetCicdDeployItemByName(name string) (*CicdDeployItem, error) {

	var dbObj CicdDeployItem
	err := Db.Where("name = ?", name).First(&dbObj).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("CicdDeployItem不存在")
		}
		return nil, fmt.Errorf("数据库错误:%w", err)
	}
	return &dbObj, nil

}
